/****************************************************************************

 Copyright (C) 2009 Jean Pierre Charalambos. All rights reserved.

 Jean Pierre Charalambos (http://dis.unal.edu.co/profesores/pierre/) is an
 Affiliate Associate Professor of the Faculty of Engineering at National
 University of Colombia (http://www.unal.edu.co/).

 This file is part of maku version 0.2.

 http://code.google.com/p/maku/
 email: jpcharalambosh@unal.edu.co

 This file may be used under the terms of the GNU General Public License
 versions 2.0 or 3.0 as published by the Free Software Foundation and
 appearing in the COPYING file included in the packaging of this file.

 This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

*****************************************************************************/

#ifndef BOUNDINGSPHERE_H
#define BOUNDINGSPHERE_H

#include <QGLViewer/qglviewer.h>

//-------------------- namespaces ----

using namespace OpenMesh;
using namespace qglviewer;
using namespace std;

class Mesh;

class BoundingSphere {
    public:
        BoundingSphere() {
            radius = 1;
            center[0] = 0;
            center[1] = 0;
            center[2] = 0;
        };
        BoundingSphere ( const float & r, const Vec3f & c ) {
            radius = r;
            center = c;
        };
        virtual ~BoundingSphere() {};
        virtual void setTightBoundingSphere ( const Mesh & ) {};
        void set ( const Vec3f & vMin, const Vec3f & vMax ) {
            setCenter ( ( vMin + vMax ) / 2 );
            setRadius ( ( ( vMax - vMin ).norm() ) /2 );
        }
        void setRadius ( const float & r ) {
            radius = r;
        }
        void setCenter ( const Vec3f & c ) {
            center = c;
        }
        const float& getRadius ( void ) const {
            return radius;
        }
        const Vec3f& getCenter ( void ) const {
            return center;
        }
        inline float distance2Center ( const Vec3f & mP ) const {
            return ( float ) distance2Center ( mP[0], mP[1], mP[2] );
        }
        inline float distance2Center ( const float x, const float y, const float z ) const {
            float a = center[0]-x;
            float b = center[1]-y;
            float c = center[2]-z;
            return ( float ) sqrt ( a*a + b*b + c*c );
        }
        inline bool isIn ( const Camera* camera ) const {
            return isIn ( camera->position().x, camera->position().y, camera->position().z );
        }
        inline bool isIn ( const Vec3f & mP ) const {
            if ( distance2Center ( mP ) > radius )
                return false;
            return true;
        }
        inline bool isIn ( const float x, const float y, const float z ) const {
            if ( distance2Center ( x, y, z ) > radius )
                return false;
            return true;
        }
        void draw ( GLint slices = 50, GLint stacks = 50 ) const {
            GLfloat curColor[4];
            glGetFloatv ( GL_CURRENT_COLOR, curColor );
            float red = 0, green = 0, blue = 1;
            glColor4f ( red, green, blue, 0.2f );
            glDisable ( GL_LIGHTING );
            //alternativa 1
            //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
            //alternativa 2
            /**
            glEnable(GL_POLYGON_STIPPLE);
            GLubyte data[32*4];
            for(int i=0;i<32*4;++i) data[i]=rand();
            glPolygonStipple( data );
            // */
            //alternativa 3
            // /**
            glEnable ( GL_BLEND );
            glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
            glDepthMask ( GL_FALSE );
            // */

            GLUquadric *myQuad;
            GLint mode;
            glGetIntegerv ( GL_MATRIX_MODE, &mode );
            glMatrixMode ( GL_MODELVIEW );

            glPushMatrix();
            glTranslatef ( center[0], center[1], center[2] );
            myQuad=gluNewQuadric();
            gluSphere ( myQuad, ( GLdouble ) radius, slices, stacks );
            glPopMatrix();

            //alternativa 1:
            //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
            //alternativa 2:
            //glDisable(GL_POLYGON_STIPPLE);
            //alternativa 3:
            // /**
            glDisable ( GL_BLEND );
            glDepthMask ( GL_TRUE );
            // */
            //
            glColor4fv ( curColor );
            glMatrixMode ( mode );
            glEnable ( GL_LIGHTING );
        }


    protected:
        float                          radius;
        Vec3f                          center;
};

#endif
